package com.itbupt.eat.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.itbupt.eat.common.BaseContext;
import com.itbupt.eat.common.CustomException;
import com.itbupt.eat.dto.OrderDto;
import com.itbupt.eat.entity.*;
import com.itbupt.eat.mapper.OrderMapper;
import com.itbupt.eat.service.IOrderService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;

/**
 * @Author BUPT-Dingchang
 * @Create 2024/5/2 1:50
 * ClassName: OrderServiceImpl
 * Description:
 */

@Slf4j
@Service
public class OrderServiceImpl extends ServiceImpl<OrderMapper, Orders> implements IOrderService {

    @Autowired
    private UserServiceImpl userService;
    @Autowired
    private AddressBookServiceImpl addressBookService;
    @Autowired
    private ShoppingCartServiceImpl shoppingCartService;
    @Autowired
    private OrderDetailServiceImpl orderDetailService;





    /**
     * 提交(添加)订单
     * @param orders 用户订单
     * @return
     */
    @Override
    @Transactional
    public Boolean submit(Orders orders) {

        // 1. 获取当前用户登陆id
        Long userId = BaseContext.getCurrentUserId();

        // 2. 调用购物车ShoppingCart业务层的获取购物车信息
        LambdaQueryWrapper<ShoppingCart> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(userId != null ,ShoppingCart::getUserId, userId);
        List<ShoppingCart> shoppingCarts = shoppingCartService.list(queryWrapper);

        // 如果购物车为空，抛出业务异常
        if(shoppingCarts.isEmpty()){
            throw new CustomException("购物车为空, 无法结算");
        }

        // 3. 调用地址簿AddressBook业务层获取当前派送的地址信息
        AddressBook addressBook = addressBookService.getById(orders.getAddressBookId());
        if(addressBook == null){
            throw new CustomException("地址信息为空，无法下单");
        }

        // 4. 调用用户业务层获取用户信息
        User user = userService.getById(userId);

        // 5. 为订单对象的属性赋值
        long orderId = IdWorker.getId();
        // 使用AtomicInteger计算商品总金额，保证高并发下的线程安全
        AtomicInteger amount = new AtomicInteger(0);

        // 6.新增订单明细，用购物车的stream流复制
        List<OrderDetail> orderDetails = shoppingCarts.stream().map(shoppingCart -> {
            OrderDetail orderDetail = new OrderDetail();
            // 复制属性值
            orderDetail.setOrderId(orderId);
            orderDetail.setNumber(shoppingCart.getNumber());
            orderDetail.setDishFlavor(shoppingCart.getDishFlavor());
            orderDetail.setDishId(shoppingCart.getDishId());
            orderDetail.setSetmealId(shoppingCart.getSetmealId());
            orderDetail.setName(shoppingCart.getName());
            orderDetail.setImage(shoppingCart.getImage());
            orderDetail.setAmount(shoppingCart.getAmount());

            // 计算订单总金额
            amount.addAndGet(shoppingCart.getAmount().multiply(new BigDecimal(shoppingCart.getNumber())).intValue());
            return orderDetail;

        }).collect(Collectors.toList());

        // 生成并设置订单号
        orders.setNumber(String.valueOf(orderId));
        // 设置下单用户id
        orders.setId(userId);
        // 设置订单状态为待派送
        orders.setStatus(2);
        // 设置商品总金额
        orders.setAmount(new BigDecimal(amount.get()));
        // 设置订单客户手机号
        orders.setPhone(addressBook.getPhone());
        // 设置收货人姓名
        orders.setConsignee(addressBook.getConsignee());
        // 设置用户名
        orders.setUserName(user.getName());

        // 设置地址详情，包含省市区
        orders.setAddress((addressBook.getProvinceName() == null ? "" : addressBook.getProvinceName())
                      + (addressBook.getCityName() == null ? "" : addressBook.getCityName())
                      + (addressBook.getDistrictName() == null ? "" : addressBook.getDistrictName())
                      + addressBook.getDetail());


         // 7.调用订单数据层新增订单
        this.save(orders);

        // 8.批量新增订单明细
        orderDetailService.saveBatch(orderDetails);

        // 9. 下单后清空购物车数据
        return shoppingCartService.remove(queryWrapper);

    }


    /**
     * 用户订单分页显示
     * @param page 当前页
     * @param pageSize 每页显示几条记录
     * @return Page
     */
    @Override
    public Page<OrderDto> getPage(Long page, Long pageSize) {

        // 1. 创建分页封装器
        Page<Orders> orderPage = new Page<>(page, pageSize);
        // 2. 创建orderDto的分页封装器
        Page<OrderDto> dtoPage = new Page<>(page, pageSize);

        // 3. 创建order查询的条件构造器
        LambdaQueryWrapper<Orders> queryWrapper = new LambdaQueryWrapper<>();
        // 按照下单时间降序排序
        queryWrapper.orderByDesc(Orders::getOrderTime);
        // 按照当前用户id查询
        Long userId = BaseContext.getCurrentUserId();
        queryWrapper.eq(userId != null, Orders::getUserId, userId);
        // 4. 分页查询
        this.page(orderPage, queryWrapper);

        // 5.除了Record都复制
        BeanUtils.copyProperties(orderPage, dtoPage, "records");

        // 6. 获取当前用户的所有订单信息
        List<Orders> orders = this.list(queryWrapper);

        // 7. 将Order转换为OrderDto
        List<OrderDto> orderDtos = orders.stream().map(order -> {
            // 创建OrderDto对象
            OrderDto orderDto = new OrderDto();
            // 复制属性值
            BeanUtils.copyProperties(order, orderDto);
            // 调用OrderDetail业务层获取订单明细集合
            LambdaQueryWrapper<OrderDetail> detailQueryWrapper = new LambdaQueryWrapper<>();
            detailQueryWrapper.eq(OrderDetail::getOrderId, order.getNumber());
            List<OrderDetail> orderDetails = orderDetailService.list(detailQueryWrapper);
             // 设置orderDto的订单明细属性
            orderDto.setOrderDetails(orderDetails);
            return orderDto;
        }).collect(Collectors.toList());

        // 8. 设置orderDto的订单信息
        dtoPage.setRecords(orderDtos);

        return dtoPage;
    }

    /**
     * 后台管理端获取订单分页展示
     * @param page  当前页
     * @param pageSize  每页显示条数
     * @param number    订单号
     * @param beginTime 开始时间
     * @param endTime   结束时间
     * @return  订单分页展示
     */
    @Override
    public Page<OrderDto> getAllPage(Long page, Long pageSize, String number, String beginTime, String endTime) {

        Page<Orders> orderPage = new Page<>(page, pageSize);
        Page<OrderDto> dtoPage = new Page<>(page, pageSize);

        LambdaQueryWrapper<Orders> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.orderByDesc(Orders::getOrderTime);
        queryWrapper.like(number != null, Orders::getNumber, number);
        // 添加查询条件：  动态SQL-字符串使用StringUtils.isNotEmpty这个方法来判断
        queryWrapper.gt(StringUtils.isNotEmpty(beginTime), Orders::getOrderTime, beginTime);
        queryWrapper.lt(StringUtils.isNotEmpty(endTime), Orders::getOrderTime, endTime);
        // Orders分页查询
        this.page(orderPage, queryWrapper);

        BeanUtils.copyProperties(orderPage, dtoPage, "records");

        // 获取当前用户所有的order对象
        List<Orders> orders = this.list(queryWrapper);
        // 通过stream流逐一包装成OrderDto对象
        List<OrderDto> orderDtos = orders.stream().map(order -> {
            // 创建OrderDto对象
            OrderDto orderDto = new OrderDto();
            // 拷贝属性
            BeanUtils.copyProperties(order, orderDto);
            // 调用OrderDetail业务层获取订单明细集合
            LambdaQueryWrapper<OrderDetail> orderDetailLqw = new LambdaQueryWrapper<>();
            orderDetailLqw.eq(OrderDetail::getOrderId, order.getNumber());
            List<OrderDetail> orderDetails = orderDetailService.list(orderDetailLqw);
            // 设置orderDto的订单明细属性
            orderDto.setOrderDetails(orderDetails);
            // 返回orderDto
            return orderDto;
        }).collect(Collectors.toList());

        dtoPage.setRecords(orderDtos);
        return dtoPage;
    }


    /**
     * 修改订单状态
     * @param order 订单对象
     * @return  是否修改成功
     */
    @Override
    public Boolean update(Orders order) {
        return this.updateById(order);
    }
}
